using System;
using System.Collections.Generic;

namespace twistmachinev2.OPCUA
{
    /// <summary>
    /// OPCUA数据订阅者接口
    /// </summary>
    public interface IOpcUaDataSubscriber
    {
        /// <summary>
        /// 处理数据变化
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="value">新值</param>
        void OnDataChanged(string nodeId, object value);
        
        /// <summary>
        /// 处理连接状态变化
        /// </summary>
        /// <param name="isConnected">是否已连接</param>
        void OnConnectionStatusChanged(bool isConnected);
    }
    
    /// <summary>
    /// OPCUA数据订阅管理器
    /// </summary>
    public class OpcUaSubscriptionManager
    {
        private static OpcUaSubscriptionManager _instance;
        private static readonly object _lock = new object();
        
        private readonly List<IOpcUaDataSubscriber> _subscribers;
        private readonly Dictionary<string, List<IOpcUaDataSubscriber>> _nodeSubscribers;
        
        private OpcUaSubscriptionManager()
        {
            _subscribers = new List<IOpcUaDataSubscriber>();
            _nodeSubscribers = new Dictionary<string, List<IOpcUaDataSubscriber>>();
            
            // 订阅服务管理器的事件
            var serviceManager = OpcUaServiceManager.Instance;
            serviceManager.DataChanged += OnServiceDataChanged;
            serviceManager.ConnectionStatusChanged += OnServiceConnectionStatusChanged;
        }
        
        /// <summary>
        /// 获取单例实例
        /// </summary>
        public static OpcUaSubscriptionManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new OpcUaSubscriptionManager();
                        }
                    }
                }
                return _instance;
            }
        }
        
        /// <summary>
        /// 订阅所有数据变化
        /// </summary>
        /// <param name="subscriber">订阅者</param>
        public void Subscribe(IOpcUaDataSubscriber subscriber)
        {
            if (subscriber != null && !_subscribers.Contains(subscriber))
            {
                _subscribers.Add(subscriber);
            }
        }
        
        /// <summary>
        /// 订阅特定节点的数据变化
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="subscriber">订阅者</param>
        public void Subscribe(string nodeId, IOpcUaDataSubscriber subscriber)
        {
            if (string.IsNullOrEmpty(nodeId) || subscriber == null)
                return;
                
            if (!_nodeSubscribers.ContainsKey(nodeId))
            {
                _nodeSubscribers[nodeId] = new List<IOpcUaDataSubscriber>();
            }
            
            if (!_nodeSubscribers[nodeId].Contains(subscriber))
            {
                _nodeSubscribers[nodeId].Add(subscriber);
            }
        }
        
        /// <summary>
        /// 取消订阅所有数据变化
        /// </summary>
        /// <param name="subscriber">订阅者</param>
        public void Unsubscribe(IOpcUaDataSubscriber subscriber)
        {
            if (subscriber == null)
                return;
                
            _subscribers.Remove(subscriber);
            
            // 从所有节点订阅中移除
            foreach (var nodeSubscribers in _nodeSubscribers.Values)
            {
                nodeSubscribers.Remove(subscriber);
            }
        }
        
        /// <summary>
        /// 取消订阅特定节点
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="subscriber">订阅者</param>
        public void Unsubscribe(string nodeId, IOpcUaDataSubscriber subscriber)
        {
            if (string.IsNullOrEmpty(nodeId) || subscriber == null)
                return;
                
            if (_nodeSubscribers.ContainsKey(nodeId))
            {
                _nodeSubscribers[nodeId].Remove(subscriber);
            }
        }
        
        /// <summary>
        /// 处理服务管理器的数据变化事件
        /// </summary>
        private void OnServiceDataChanged(object sender, DataChangedEventArgs e)
        {
            // 通知全局订阅者
            foreach (var subscriber in _subscribers.ToArray())
            {
                try
                {
                    subscriber.OnDataChanged(e.NodeId, e.Value);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"通知订阅者数据变化失败: {ex.Message}");
                }
            }
            
            // 通知特定节点的订阅者
            if (_nodeSubscribers.ContainsKey(e.NodeId))
            {
                foreach (var subscriber in _nodeSubscribers[e.NodeId].ToArray())
                {
                    try
                    {
                        subscriber.OnDataChanged(e.NodeId, e.Value);
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine($"通知节点订阅者数据变化失败: {ex.Message}");
                    }
                }
            }
        }
        
        /// <summary>
        /// 处理服务管理器的连接状态变化事件
        /// </summary>
        private void OnServiceConnectionStatusChanged(object sender, ConnectionStatusChangedEventArgs e)
        {
            // 通知所有订阅者
            foreach (var subscriber in _subscribers.ToArray())
            {
                try
                {
                    subscriber.OnConnectionStatusChanged(e.IsConnected);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"通知订阅者连接状态变化失败: {ex.Message}");
                }
            }
            
            // 通知所有节点订阅者
            foreach (var nodeSubscribers in _nodeSubscribers.Values)
            {
                foreach (var subscriber in nodeSubscribers.ToArray())
                {
                    try
                    {
                        subscriber.OnConnectionStatusChanged(e.IsConnected);
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine($"通知节点订阅者连接状态变化失败: {ex.Message}");
                    }
                }
            }
        }
    }
}